#region Using
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
#endregion

public class Pool {
	#region Variables
	private GameObject master;
	private string name;
	private bool allowRuntimeCreation;
	
	private ArrayList available;
	private ArrayList inUse;
	#endregion

	#region Constructor
	public Pool(GameObject poolMaster, int size, string poolName, bool allowRuntimeObjectCreation) 
	{
		master = poolMaster;
		allowRuntimeCreation = allowRuntimeObjectCreation;
		name = poolName;
		available = new ArrayList(size);
		inUse = new ArrayList(size);
		
		for (int i = 0; i < size; i++) 
		{
			GameObject newObj = (GameObject)Object.Instantiate(poolMaster);
			newObj.name = name;
			newObj.transform.parent = PoolManager.Instance.actorTransform;

			newObj.SetActive(false);
			available.Add(newObj);
			newObj.BroadcastMessage("Start", SendMessageOptions.DontRequireReceiver);
		}
	}
	#endregion

	#region Public
	public GameObject GetObject() 
	{
		GameObject obj = null;
		if (available.Count > 0) 
		{
			obj = (GameObject)available[available.Count-1];
			available.RemoveAt(available.Count-1);
		} 
		else if (allowRuntimeCreation)
		{
			//	None remaining in the available pool and we CAN create new object at runtime...
			//	Instanciate 1 new object.
			//available.Capacity = Mathf.CeilToInt(available.Count * 1.1f);
			//inUse.Capacity = available.Capacity;
			
			Debug.Log("Pool Instantiate: " + master.name);
			
			obj = (GameObject)Object.Instantiate(master);
			obj.BroadcastMessage("Start", SendMessageOptions.DontRequireReceiver);
		} 
		else if (inUse.Count > 0){
			//	None remaining in the available pool and we CAN'T create new object at runtime...
			//	Pick the oldest one in the inUse queue.
			obj = (GameObject)inUse[0];
			inUse.RemoveAt(0);
		}
		if (obj != null) 
		{
			obj.SetActive(true);
			obj.name = name;
			inUse.Add(obj);
		}
		return obj;
	}
	
	public void ReleaseObject(GameObject toRelease) 
	{
		toRelease.SetActive(false);
		int index = inUse.IndexOf(toRelease);
 		inUse.RemoveAt(index);
		available.Add(toRelease);
	}

	public void Destroy() 
	{
		foreach(Object o in new ArrayList(inUse)) {
			ReleaseObject(o as GameObject);
		}
		
		foreach(Object o in new ArrayList(available)) {
			GameObject.Destroy(o as GameObject);
		}
		
		available.Clear();
		available = null;
		inUse.Clear();
		inUse = null;
		master = null;
	}
	#endregion
	
	#region Privates
	private void SetActiveRecursively(GameObject parent, bool active)
	{
		foreach (Transform child in parent.transform){
		    SetActiveRecursively(child.gameObject, active);
		}
		parent.SetActive(active);
	}
	#endregion
}
